/*************************************************************************
    > File Name    : SocketIO.cc
    > Author       : LiuLei
    > Mail         : 2261459486@qq.com 
    > Created Time : 2022年11月25日 星期五 10时43分59秒
 ************************************************************************/

#include "../../include/server/SocketIO.h"
#include <unistd.h> 
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>


SocketIO::SocketIO(int fd)
: _fd(fd)
{

}

SocketIO::~SocketIO()
{

}

int SocketIO::readn(void *pstr, int len)
{
    if(nullptr == pstr || len < 0)
    {
        return -1;
    }

    int left = len;
    char *buf = static_cast<char *>(pstr);
    int ret = 0;

    while(left > 0)
    {
        ret = ::read(_fd, buf, left);
        if(-1 == ret && errno == EINTR)
        {
            continue;
        }
        else if(-1 == ret)
        {
            ::perror("read -1 in SocketIO::readn");
            return len - left;
        }
        else if(0 == ret)
        {
            break;
        }
        else
        {
            buf += ret;
            left -= ret;
        }
    }
    return len - left;
}

int SocketIO::readLine(void *pstr, int len)
{
    int left = len - 1;
    //保留一位给空字符
    char *buf = static_cast<char *>(pstr);
    int ret = 0, total = 0;

    while(left > 0)
    {
        ret = ::recv(_fd, buf, left, MSG_PEEK);
        /* ret = ::read(_fd, buf, left); */
        /* MSG_PEEK不会将缓冲区的数据清空，只会进行拷贝操作 */
        if(-1 == ret && errno == EINTR)
        {
            continue;
        }
        else if(-1 == ret)
        {
            ::perror("recv -1 in SocketIO::readLine()");
            return len - left;
        }
        else if(0 == ret)
        {
            break;
        }
        else
        {
            //找换行符
            for(int idx = 0; idx < ret; ++idx)
            {
                if('\n' == buf[idx])
                {
                    int sz = idx + 1;
                    //找到换行符，总共要读取sz个字符
                    readn(buf, sz);
                    //结尾为'\0'
                    buf += sz;
                    *buf = '\0';

                    return total + sz;
                }
            }
            //没找到
            readn(buf, ret);
            total += ret;
            buf += ret;
            left -= ret;
        }
    }
    //读取了len个字节仍然没有读到'\n'
    *buf = '\0';
    return total - left;
}

int SocketIO::readJson(void *pstr, int len)
{
    int left = len - 1;
    char *buf = static_cast<char *>(pstr);
    int ret = 0, total = 0;

    while(left > 0)
    {
        ret = ::recv(_fd, buf, left, MSG_PEEK);

        if(-1 == ret && errno == EINTR)
        {
            continue;
        }
        else if(-1 == ret)
        {
            ::perror("recv -1 in SocketIO::readJson()");
            return len - left;
        }
        else if(0 == ret)
        {
            break;
        }
        else
        {
            for(int idx = 0; idx < ret; ++idx)
            {
                if('\0' == buf[idx])
                {
                    int sz = idx + 1;
                    readn(buf, sz);
                    buf += sz;

                    return total + sz;
                }
            }

            readn(buf, ret);
            total += ret;
            buf += ret;
            left -= ret;
        }
    }
    //读取了len个字节仍然没有读到'\0'
    *buf = '\0';
    return total - left;
}

int SocketIO::wriren(const char *pstr, int len)
{
    int left = len;
    const char *buf = pstr;
    int ret = 0;
    while(left > 0)
    {
        ret = ::write(_fd, buf, left);
        if(-1 == ret && errno == EINTR)
        {
            continue;
        }
        else if(-1 == ret)
        {
            ::perror("write error : -1");
            return len - left;
        }
        else if(0 == ret)
        {
            break;
        }
        else
        {
            buf += ret;
            left -= ret;
        }
    }
    return len - left;
}
